package com.settlement.system.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.settlement.system.common.annotation.PreventDuplicateSubmit;
import com.settlement.system.common.base.IBaseEnum;
import com.settlement.system.common.enums.*;
import com.settlement.system.common.result.PageResult;
import com.settlement.system.common.result.Result;
import com.settlement.system.common.util.NumberUtils;
import com.settlement.system.common.util.RequestUtils;
import com.settlement.system.common.util.StringUtils;
import com.settlement.system.listener.easyexcel.SysOrderListener;
import com.settlement.system.model.entity.SysAddress;
import com.settlement.system.model.entity.SysAmazon;
import com.settlement.system.model.entity.SysCreditCard;
import com.settlement.system.model.entity.SysOrder;
import com.settlement.system.model.form.SysOrderForm;
import com.settlement.system.model.query.SysOrderQuery;
import com.settlement.system.model.vo.*;
import com.settlement.system.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 刷单表 前端控制器
 * </p>
 *
 * @author huangrensen
 * @since 2024-07-17
 */
@RestController
@RequestMapping("/api/v1/order")
@RequiredArgsConstructor
public class SysOrderController {

    @Value("${system.config.secret}")
    private String secret;

    @Value("${system.config.appId}")
    private String appId;

    private final SysOrderService sysOrderService;

    private final SysOrderLogService orderLogService;

    private final SysAmazonService amazonService;

    private final SysAddressService addressService;

    private final SysCreditCardService creditCardService;

    @Operation(summary = "清空任务队列", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/emptyQueue")
    @PreventDuplicateSubmit
    @PreAuthorize("@ss.hasPerm('sys:order:emptyQueue')")
    public Result<?> emptyQueue() {
        AmazonContext.REGISTER_AMAZON_QUEUE.clear();
        AmazonContext.REGISTER_EMAIL_QUEUE.clear();
        AmazonContext.SHOPPING_QUEUE.clear();
        AmazonContext.WISH_LIST_QUEUE.clear();
        return Result.success();
    }

    @Operation(summary = "获取注册邮箱队列任务列表(返回前50条)", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/emailQueue")
    public Result<List<RegisterEmailVo>> emailQueue() {
        // 获取队列前50条任务
        List<RegisterEmailVo> registerEmailVoList = new ArrayList<>(AmazonContext.REGISTER_EMAIL_QUEUE.stream().limit(50).toList());
        for (RegisterEmailVo registerEmailVo : registerEmailVoList) {
            registerEmailVo.setStatusName(IBaseEnum.getLabelByValue(registerEmailVo.getStatus(), RegisterEmailStatusEnum.class));
        }
        return Result.success(registerEmailVoList);
    }

    @Operation(summary = "邮箱进入下一步", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/emailNext")
    public Result<?> emailNext() {
        if (!AmazonContext.REGISTER_EMAIL_QUEUE.isEmpty()) {
            RegisterEmailVo emailVo = AmazonContext.REGISTER_EMAIL_QUEUE.poll();
            SysOrder sysOrder = sysOrderService.getBaseMapper().selectOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getEmail, emailVo.getEmail()));
            sysOrder.setStatus(SysOrderStatusEnum.SHOPPING.getValue());
            sysOrderService.updateById(sysOrder);
            orderLogService.saveSysOrderLog(emailVo.getEmail(), "注册邮箱成功");
            RegisterAmazonVo amazonVo = new RegisterAmazonVo();
            BeanUtils.copyProperties(sysOrder, amazonVo);
            amazonVo.setStatus(RegisterAmazonStatusEnum.WAITING.getValue());
            // 添加任务到注册亚马逊队列
            AmazonContext.REGISTER_AMAZON_QUEUE.add(amazonVo);
        }
        return Result.success();
    }

    @Operation(summary = "获取注册亚马逊队列任务列表(返回前50条)", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/amazonQueue")
    public Result<List<RegisterAmazonVo>> amazonQueue() {
        List<RegisterAmazonVo> registerAmazonVoList;
        // 获取队列前50条任务
        registerAmazonVoList = AmazonContext.REGISTER_AMAZON_QUEUE.stream().limit(50).toList();
        for (RegisterAmazonVo amazonVo : registerAmazonVoList) {
            amazonVo.setStatusName(IBaseEnum.getLabelByValue(amazonVo.getStatus(), RegisterAmazonStatusEnum.class));
        }
        return Result.success(registerAmazonVoList);
    }

    @Operation(summary = "亚马逊进入下一步", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/amazonNext")
    public Result<?> amazonNext() {
        if (!AmazonContext.REGISTER_AMAZON_QUEUE.isEmpty()) {
            RegisterAmazonVo amazonVo = AmazonContext.REGISTER_AMAZON_QUEUE.poll();
            SysOrder sysOrder = sysOrderService.getBaseMapper().selectOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getEmail, amazonVo.getEmail()));
            sysOrder.setStatus(SysOrderStatusEnum.SHOPPING.getValue());
            sysOrderService.updateById(sysOrder);
            orderLogService.saveSysOrderLog(amazonVo.getEmail(), "注册亚马逊成功");
            AmazonShoppingVo shoppingVo = new AmazonShoppingVo();
            BeanUtils.copyProperties(sysOrder, shoppingVo);
            shoppingVo.setStatus(AmazonShoppingStatusEnum.WAITING.getValue());
            // 添加任务到购物队列
            AmazonContext.SHOPPING_QUEUE.add(shoppingVo);
        }
        return Result.success();
    }

    @Operation(summary = "获取购物队列任务列表(返回前50条)", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/shoppingQueue")
    public Result<List<AmazonShoppingVo>> shoppingQueue() {
        List<AmazonShoppingVo> amazonShoppingVoList;
        // 获取队列前50条任务
        amazonShoppingVoList = AmazonContext.SHOPPING_QUEUE.stream().limit(50).toList();
        List<String> emailList = amazonShoppingVoList.stream().map(AmazonShoppingVo::getEmail).distinct().toList();
        List<String> shortNameList = amazonShoppingVoList.stream().map(AmazonShoppingVo::getShortName).distinct().toList();
        List<SysAmazon> sysAmazonList;
        if(emailList.size() > 0){
            sysAmazonList = amazonService.list(new LambdaQueryWrapper<SysAmazon>().in(SysAmazon::getEmail, emailList));
        }else{
            sysAmazonList = new ArrayList<>();
        }
        List<SysAddress> sysAddressList;
        if(shortNameList.size() > 0){
            sysAddressList = addressService.list(new LambdaQueryWrapper<SysAddress>().in(SysAddress::getShortName, shortNameList));
        }else{
            sysAddressList = new ArrayList<>();
        }
        SysAmazon amazon;
        SysAddress address;
        for (AmazonShoppingVo shoppingVo : amazonShoppingVoList) {
            amazon = sysAmazonList.stream().filter(a -> Objects.equals(a.getEmail(), shoppingVo.getEmail())).findFirst().orElse(null);
            if (Objects.nonNull(amazon)) {
                shoppingVo.setPassword(amazon.getPassword());
            }
            address = sysAddressList.stream().filter(a -> Objects.equals(a.getShortName(), shoppingVo.getShortName())).findFirst().orElse(null);
            if (Objects.nonNull(address)) {
                // 收货人姓名
                shoppingVo.setReceiver(address.getUserName());
                // 电话号码
                shoppingVo.setMobile(address.getPhone());
                // 街道地址
                shoppingVo.setStreet(address.getStreet());
            }
            shoppingVo.setStatusName(IBaseEnum.getLabelByValue(shoppingVo.getStatus(), AmazonShoppingStatusEnum.class));
        }
        return Result.success(amazonShoppingVoList);
    }

    @Operation(summary = "购物进入下一步", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/shoppingNext")
    public Result<?> shoppingNext() {
        if (!AmazonContext.SHOPPING_QUEUE.isEmpty()) {
            AmazonShoppingVo shoppingVo = AmazonContext.SHOPPING_QUEUE.poll();
            SysOrder sysOrder = sysOrderService.getBaseMapper().selectOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getEmail, shoppingVo.getEmail()));
            orderLogService.saveSysOrderLog(shoppingVo.getEmail(), "购物成功");
            sysOrder.setStatus(SysOrderStatusEnum.FINISH.getValue());
            sysOrderService.updateById(sysOrder);
        }
        return Result.success();
    }

    @Operation(summary = "获取心愿单队列任务列表(返回前50条)", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/wishQueue")
    public Result<List<AmazonWishVo>> wishQueue() {
        List<AmazonWishVo> amazonWishVoList;
        // 获取队列前50条任务
        amazonWishVoList = AmazonContext.WISH_LIST_QUEUE.stream().limit(50).toList();
        for (AmazonWishVo wishVo : amazonWishVoList) {
            wishVo.setStatusName(IBaseEnum.getLabelByValue(wishVo.getStatus(), AmazonWishStatusEnum.class));
        }
        return Result.success(amazonWishVoList);
    }

    @Operation(summary = "心愿单进入下一步", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/wishNext")
    public Result<?> wishNext() {
        if (!AmazonContext.WISH_LIST_QUEUE.isEmpty()) {
            AmazonWishVo wishVo = AmazonContext.WISH_LIST_QUEUE.poll();
            SysOrder sysOrder = sysOrderService.getBaseMapper().selectOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getEmail, wishVo.getEmail()));
            orderLogService.saveSysOrderLog(wishVo.getEmail(), "添加心愿单成功");
            sysOrder.setStatus(SysOrderStatusEnum.FINISH.getValue());
            sysOrderService.updateById(sysOrder);
        }
        return Result.success();
    }

    @Operation(summary = "刷单表分页", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/page")
    public PageResult<SysOrder> getPage(@ParameterObject SysOrderQuery queryParams) {
        Page<SysOrder> result = sysOrderService.getPage(queryParams);
        return PageResult.success(result);
    }

    @Operation(summary = "获取5条购物任务")
    @GetMapping("/getShoppingMissions")
    public Result<?> getShoppingMissions(HttpServletRequest request) {
        Result<?> result = RequestUtils.resolveAppToken(request, secret, appId);
        if (!Result.isSuccess(result)) {
            return result;
        }
        List<AmazonShoppingVo> shoppingVos = new ArrayList<>();
        if (!AmazonContext.SHOPPING_QUEUE.isEmpty()) {
            for (AmazonShoppingVo shoppingVo : AmazonContext.SHOPPING_QUEUE) {
                shoppingVos.add(shoppingVo);
                if (shoppingVos.size() >= 5) {
                    break;
                }
            }
        }
        return Result.success(shoppingVos);
    }


    @Operation(summary = "保存刷单表", security = {@SecurityRequirement(name = "Authorization")})
    @PostMapping
    @PreventDuplicateSubmit
    @PreAuthorize("@ss.hasPerm('sys:order:save')")
    public Result<?> saveSysOrder(@RequestBody @Valid SysOrderForm sysOrderForm) {
        boolean result = sysOrderService.saveSysOrder(sysOrderForm);
        return Result.judge(result);
    }

    @Operation(summary = "获取刷单表信息", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/{id}/form")
    public Result<SysOrderForm> getSysOrderFormData(@Parameter(description = "主键ID") @PathVariable Long id) {
        SysOrderForm sysOrder = sysOrderService.getSysOrderFormData(id);
        return Result.success(sysOrder);
    }

    @Operation(summary = "删除刷单表", security = {@SecurityRequirement(name = "Authorization")})
    @DeleteMapping("/{ids}")
    @PreAuthorize("@ss.hasPerm('sys:order:delete')")
    public Result<?> deleteSysOrder(@Parameter(description = "ID，多个以英文逗号(,)分割") @PathVariable String ids) {
        boolean result = sysOrderService.deleteSysOrder(ids);
        return Result.judge(result);
    }

    @Operation(summary = "刷单表导入", security = {@SecurityRequirement(name = "Authorization")})
    @PostMapping("/sysOrderImport")
    @PreAuthorize("@ss.hasPerm('sys:order:import')")
    @PreventDuplicateSubmit
    public Result<?> sysOrderImport(@RequestParam("file") MultipartFile file) throws Exception {
        SysOrderListener listener = new SysOrderListener();
        EasyExcelFactory.read(file.getInputStream(), SysOrderImportVo.class, listener).sheet(0).doRead();
        List<SysOrderImportVo> list = listener.getVos();
        if (list == null || list.size() == 0) {
            return Result.success();
        }
        list.removeIf(item -> !StringUtils.hasText(item.getEmail()));
        // 检查信用卡不能为空
        Assert.isTrue(list.stream().allMatch(item -> StringUtils.hasText(item.getCardNo())), "卡号不能为空");
        Assert.isTrue(list.stream().allMatch(item -> StringUtils.hasText(item.getProductUrl())), "购买链接不能为空");
        Assert.isTrue(list.stream().allMatch(item -> StringUtils.hasText(item.getShortName())), "收货地址简称不能为空");
        // 检查邮箱是否使用过
        List<String> emailList = list.stream().map(SysOrderImportVo::getEmail).distinct().toList();
        // 检查邮箱是否注册成功
        List<SysAmazon> sysAmazonList = amazonService.list(new LambdaQueryWrapper<SysAmazon>().in(SysAmazon::getEmail, emailList));
        SysAmazon amazon;
        for (String mailNo : emailList) {
            amazon = sysAmazonList.stream().filter(item -> Objects.equals(mailNo, item.getEmail())).findFirst().orElse(null);
            if (Objects.isNull(amazon)) {
                return Result.failed("邮箱：【" + mailNo + " 】还没完成注册，不能使用");
            } else if (!Objects.equals(amazon.getStatus(), AmazonStatusEnum.REGISTERED.getValue())) {
                return Result.failed("邮箱：【" + mailNo + " 】还没注册成功，不能使用");
            }
        }
        // 检查地址是否使用过
        List<String> shortNameList = list.stream().map(SysOrderImportVo::getShortName).distinct().toList();
        List<String> cardNoList = list.stream().map(SysOrderImportVo::getCardNo).distinct().toList();
        List<SysCreditCard> creditCardList = creditCardService.list(new LambdaQueryWrapper<SysCreditCard>().in(SysCreditCard::getCardNo, cardNoList));
        List<SysAddress> sysAddressList = addressService.list(new LambdaQueryWrapper<SysAddress>().in(SysAddress::getShortName, shortNameList));
        List<SysAddress> hasUseAddressList = sysAddressList.stream().filter(item -> Objects.equals(item.getUseStatus(), AddressStatusEnum.HAS_USE.getValue())).toList();
        Assert.isTrue(hasUseAddressList.size() == 0, "地址：【" + hasUseAddressList.stream().map(SysAddress::getShortName).collect(Collectors.joining(",")) + " 】已被使用，不能使用");
        // 检查地址简称是否存在
        SysAddress address;
        SysCreditCard creditCard;
        for (SysOrderImportVo sysOrderImportVo : list) {
            address = sysAddressList.stream().filter(item -> Objects.equals(sysOrderImportVo.getShortName(), item.getShortName())).findFirst().orElse(null);
            Assert.isTrue(Objects.nonNull(address), "收货地址简称：【" + sysOrderImportVo.getShortName() + " 】不存在，不能使用");
        }
        sysOrderService.importData(list);
        // 清空队列任务
        AmazonContext.SHOPPING_QUEUE.clear();
        AmazonShoppingVo shoppingVo;
        for (SysOrderImportVo sysOrderImportVo : list) {
            shoppingVo = new AmazonShoppingVo();
            BeanUtils.copyProperties(sysOrderImportVo, shoppingVo);
            address = sysAddressList.stream().filter(item -> Objects.equals(sysOrderImportVo.getShortName(), item.getShortName())).findFirst().orElse(null);
            if (Objects.nonNull(address)) {
                BeanUtils.copyProperties(address, shoppingVo, "id");
            }
            // 标识为已使用
            address.setUseStatus(AddressStatusEnum.HAS_USE.getValue());
            shoppingVo.setQty(NumberUtils.convertInteger(sysOrderImportVo.getQty()));
            shoppingVo.setStatus(AmazonShoppingStatusEnum.WAITING.getValue());
            creditCard = creditCardList.stream().filter(item -> Objects.equals(sysOrderImportVo.getCardNo(), item.getCardNo())).findFirst().orElse(null);
            if (Objects.nonNull(creditCard)) {
                // 卡号
                shoppingVo.setCardNo(creditCard.getCardNo());
                // 信用卡手机号码
                shoppingVo.setCardPhone(creditCard.getMobile());
                // 姓名
                shoppingVo.setUserName(creditCard.getUserName());
                // 有效期
                shoppingVo.setValidDate(creditCard.getValidDate());
                // 安全码
                shoppingVo.setCvv(creditCard.getCvv());
            }
            // 添加任务
            AmazonContext.SHOPPING_QUEUE.add(shoppingVo);
        }
        // 更新地址
        addressService.updateBatchById(sysAddressList);
        return Result.success();
    }

    @Operation(summary = "导出刷单表", security = {@SecurityRequirement(name = "Authorization")})
    @GetMapping("/_export")
    @PreAuthorize("@ss.hasPerm('sys:order:export')")
    @PreventDuplicateSubmit
    public void export(@RequestParam("ids") String ids, HttpServletResponse response) throws IOException {
        String fileName = "刷单表.xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8));
        List<SysOrderImportVo> sysOrderList = sysOrderService.findByIds(ids);
        EasyExcel.write(response.getOutputStream(), SysOrderImportVo.class).sheet("刷单表").doWrite(sysOrderList);
    }
}

